package com.smartHome.service.impl;

import com.smartHome.mapper.EnergyMapper;
import com.smartHome.pojo.vo.EnergyConsumptionVO;
import com.smartHome.service.EnergyService;
import com.smartHome.common.TimeRangeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Service
public class EnergyServiceImpl implements EnergyService {

    private static final String[] DAY_LABELS = { "6天前", "5天前", "4天前", "3天前", "2天前", "昨天", "今天" };
    private static final String[] MONTH_LABELS = { "6个月前", "5个月前", "4个月前", "3个月前", "2个月前", "上月", "本月" };

    @Autowired
    private EnergyMapper energyMapper;

    @Override
    public EnergyConsumptionVO getHouseConsumption(Integer houseId, Integer timeRange) {
        EnergyConsumptionVO vo = new EnergyConsumptionVO();
        LocalDateTime now = LocalDateTime.now();

        // 获取当前周期的用电量（今天0点到现在 或 本月1号到现在）
        LocalDateTime currentStartTime = getCurrentPeriodStartTime(now, timeRange);
        Double currentTotal = energyMapper.getHouseConsumption(houseId, currentStartTime, now);
        vo.setTotalConsumption(currentTotal != null ? currentTotal : 0.0);

        // 获取上一周期同期数据（昨天同时段 或 上月同时段）
        LocalDateTime lastStartTime = getLastPeriodStartTime(now, timeRange);
        LocalDateTime lastEndTime = getLastPeriodEndTime(now, timeRange);
        Double lastTotal = energyMapper.getHouseConsumption(houseId, lastStartTime, lastEndTime);

        // 计算环比变化
        vo.setComparison(calculateComparison(currentTotal, lastTotal));

        // 获取趋势数据
        List<EnergyConsumptionVO.TrendData> trend = getTrendData(houseId, now, timeRange);
        vo.setTrend(trend);

        // 设置最大值（比实际最大值高20%）
        vo.setMaxValue(calculateMaxValue(trend));

        return vo;
    }

    private List<EnergyConsumptionVO.TrendData> getTrendData(Integer houseId, LocalDateTime now, Integer timeRange) {
        List<EnergyConsumptionVO.TrendData> trend = new ArrayList<>();
        String[] labels = timeRange == 1 ? DAY_LABELS : MONTH_LABELS;

        // 获取趋势数据的时间范围
        LocalDateTime trendStartTime = getTrendStartTime(now, timeRange);
        List<EnergyConsumptionVO.TrendData> rawData = energyMapper.getHouseTrend(
                houseId, trendStartTime, now, timeRange);

        // 确保返回7个数据点，没有数据的用0填充
        for (int i = 0; i < 7; i++) {
            EnergyConsumptionVO.TrendData data = new EnergyConsumptionVO.TrendData();
            data.setLabel(labels[i]);
            data.setValue(0.0); // 默认值

            // 查找对应日期的实际数据
            for (EnergyConsumptionVO.TrendData raw : rawData) {
                if (matchTrendData(raw, i, timeRange, now)) {
                    data.setValue(raw.getValue());
                    break;
                }
            }
            trend.add(data);
        }

        return trend;
    }

    private boolean matchTrendData(EnergyConsumptionVO.TrendData data, int index, Integer timeRange,
            LocalDateTime now) {
        if (timeRange == 1) {
            // 对于日视图，将数据库返回的日期（如"15"）转换为相对日期索引
            int dayOfMonth = Integer.parseInt(data.getLabel());
            int currentDay = now.getDayOfMonth();
            int daysAgo = 6 - index; // 6天前到今天
            return dayOfMonth == currentDay - daysAgo;
        } else {
            // 对于月视图，将数据库返回的月份（如"3月"）转换为相对月份索引
            int month = Integer.parseInt(data.getLabel().replace("月", ""));
            int currentMonth = now.getMonthValue();
            int monthsAgo = 6 - index; // 6个月前到本月
            return month == ((currentMonth - monthsAgo + 12) % 12);
        }
    }

    private Double calculateMaxValue(List<EnergyConsumptionVO.TrendData> trend) {
        double max = trend.stream()
                .mapToDouble(EnergyConsumptionVO.TrendData::getValue)
                .max()
                .orElse(0.0);
        return Math.round(max * 1.2 * 10.0) / 10.0; // 保留一位小数
    }

    @Override
    public EnergyConsumptionVO getRoomConsumption(Integer roomId, Integer timeRange) {
        EnergyConsumptionVO vo = new EnergyConsumptionVO();
        LocalDateTime now = LocalDateTime.now();

        // 获取当前周期的用电量（今天0点到现在 或 本月1号到现在）
        LocalDateTime currentStartTime = getCurrentPeriodStartTime(now, timeRange);
        Double currentTotal = energyMapper.getRoomConsumption(roomId, currentStartTime, now);
        vo.setTotalConsumption(currentTotal != null ? currentTotal : 0.0);

        // 获取上一周期同期数据（昨天同时段 或 上月同时段）
        LocalDateTime lastStartTime = getLastPeriodStartTime(now, timeRange);
        LocalDateTime lastEndTime = getLastPeriodEndTime(now, timeRange);
        Double lastTotal = energyMapper.getRoomConsumption(roomId, lastStartTime, lastEndTime);

        // 计算环比变化
        vo.setComparison(calculateComparison(currentTotal, lastTotal));

        // 获取趋势数据
        List<EnergyConsumptionVO.TrendData> trend = getTrendDataForRoom(roomId, now, timeRange);
        vo.setTrend(trend);

        // 设置最大值（比实际最大值高20%）
        vo.setMaxValue(calculateMaxValue(trend));

        return vo;
    }

    @Override
    public EnergyConsumptionVO getDeviceConsumption(Integer deviceId, Integer timeRange) {
        EnergyConsumptionVO vo = new EnergyConsumptionVO();
        LocalDateTime now = LocalDateTime.now();

        // 获取当前周期的用电量（今天0点到现在 或 本月1号到现在）
        LocalDateTime currentStartTime = getCurrentPeriodStartTime(now, timeRange);
        Double currentTotal = energyMapper.getDeviceConsumption(deviceId, currentStartTime, now);
        vo.setTotalConsumption(currentTotal != null ? currentTotal : 0.0);

        // 获取上一周期同期数据（昨天同时段 或 上月同时段）
        LocalDateTime lastStartTime = getLastPeriodStartTime(now, timeRange);
        LocalDateTime lastEndTime = getLastPeriodEndTime(now, timeRange);
        Double lastTotal = energyMapper.getDeviceConsumption(deviceId, lastStartTime, lastEndTime);

        // 计算环比变化
        vo.setComparison(calculateComparison(currentTotal, lastTotal));

        // 获取趋势数据
        List<EnergyConsumptionVO.TrendData> trend = getTrendDataForDevice(deviceId, now, timeRange);
        vo.setTrend(trend);

        // 设置最大值（比实际最大值高20%）
        vo.setMaxValue(calculateMaxValue(trend));

        return vo;
    }

    private List<EnergyConsumptionVO.TrendData> getTrendDataForRoom(Integer roomId, LocalDateTime now,
            Integer timeRange) {
        List<EnergyConsumptionVO.TrendData> trend = new ArrayList<>();
        String[] labels = timeRange == 1 ? DAY_LABELS : MONTH_LABELS;

        // 获取趋势数据的时间范围
        LocalDateTime trendStartTime = getTrendStartTime(now, timeRange);
        List<EnergyConsumptionVO.TrendData> rawData = energyMapper.getRoomTrend(
                roomId, trendStartTime, now, timeRange);

        // 确保返回7个数据点，没有数据的用0填充
        for (int i = 0; i < 7; i++) {
            EnergyConsumptionVO.TrendData data = new EnergyConsumptionVO.TrendData();
            data.setLabel(labels[i]);
            data.setValue(0.0); // 默认值

            // 查找对应日期的实际数据
            for (EnergyConsumptionVO.TrendData raw : rawData) {
                if (matchTrendData(raw, i, timeRange, now)) {
                    data.setValue(raw.getValue());
                    break;
                }
            }
            trend.add(data);
        }

        return trend;
    }

    private List<EnergyConsumptionVO.TrendData> getTrendDataForDevice(Integer deviceId, LocalDateTime now,
            Integer timeRange) {
        List<EnergyConsumptionVO.TrendData> trend = new ArrayList<>();
        String[] labels = timeRange == 1 ? DAY_LABELS : MONTH_LABELS;

        // 获取趋势数据的时间范围
        LocalDateTime trendStartTime = getTrendStartTime(now, timeRange);
        List<EnergyConsumptionVO.TrendData> rawData = energyMapper.getDeviceTrend(
                deviceId, trendStartTime, now, timeRange);

        // 确保返回7个数据点，没有数据的用0填充
        for (int i = 0; i < 7; i++) {
            EnergyConsumptionVO.TrendData data = new EnergyConsumptionVO.TrendData();
            data.setLabel(labels[i]);
            data.setValue(0.0); // 默认值

            // 查找对应日期的实际数据
            for (EnergyConsumptionVO.TrendData raw : rawData) {
                if (matchTrendData(raw, i, timeRange, now)) {
                    data.setValue(raw.getValue());
                    break;
                }
            }
            trend.add(data);
        }

        return trend;
    }

    @Override
    public List<String> getEnergySuggestions(Integer houseId) {
        List<String> suggestions = new ArrayList<>();

        // 获取最新的能源消耗数据
        EnergyConsumptionVO dailyData = getHouseConsumption(houseId, 1);
        double comparison = dailyData.getComparison();

        if (comparison > 0) {
            suggestions.add(String.format("本周用电量较上周增加%.1f%%，建议关注用电习惯", comparison));
        } else if (comparison < 0) {
            suggestions.add(String.format("本周用电量较上周减少%.1f%%，节能效果显著", Math.abs(comparison)));
        } else {
            suggestions.add("本周用电量与上周持平，继续保持");
        }

        suggestions.add("建议在用电高峰期（10:00-15:00）减少空调使用");
        suggestions.add("检测到部分房间无人时灯光未关闭，建议及时关闭");

        return suggestions;
    }

    private Double calculateComparison(Double current, Double last) {
        if (current == null || last == null || last == 0) {
            return 0.0;
        }
        return ((current - last) / last) * 100;
    }

    private LocalDateTime getCurrentPeriodStartTime(LocalDateTime now, Integer timeRange) {
        return switch (timeRange) {
            case 1 -> now.toLocalDate().atStartOfDay(); // 当天0点
            case 2 -> now.withDayOfMonth(1).toLocalDate().atStartOfDay(); // 本月1号0点
            default -> throw new IllegalArgumentException("Invalid time range: " + timeRange);
        };
    }

    private LocalDateTime getLastPeriodStartTime(LocalDateTime now, Integer timeRange) {
        return switch (timeRange) {
            case 1 -> now.minusDays(1).toLocalDate().atStartOfDay(); // 昨天0点
            case 2 -> now.minusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay(); // 上月1号
            default -> throw new IllegalArgumentException("Invalid time range: " + timeRange);
        };
    }

    private LocalDateTime getLastPeriodEndTime(LocalDateTime now, Integer timeRange) {
        return switch (timeRange) {
            case 1 -> now.minusDays(1).withHour(now.getHour())
                    .withMinute(now.getMinute())
                    .withSecond(now.getSecond()); // 昨天同一时刻
            case 2 -> now.minusMonths(1).withDayOfMonth(now.getDayOfMonth())
                    .withHour(now.getHour())
                    .withMinute(now.getMinute())
                    .withSecond(now.getSecond()); // 上月同一日期和时刻
            default -> throw new IllegalArgumentException("Invalid time range: " + timeRange);
        };
    }

    private LocalDateTime getTrendStartTime(LocalDateTime now, Integer timeRange) {
        return switch (timeRange) {
            case 1 -> now.minusDays(6).toLocalDate().atStartOfDay(); // 最近7天
            case 2 -> now.minusMonths(5).withDayOfMonth(1).toLocalDate().atStartOfDay(); // 最近6个月
            default -> throw new IllegalArgumentException("Invalid time range: " + timeRange);
        };
    }
}
